/**
 * @file debugger.h
 * @brief VimL虚拟机调试器头文件
 * @author VimLVM Team
 * @date 2025
 */

#pragma once

#include <memory>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <functional>

namespace viml {

class VM;
class Value;

/**
 * @brief 调试事件类型枚举
 */
enum class DebugEvent {
    BREAKPOINT_HIT,    ///< 断点命中
    STEP_COMPLETE,     ///< 单步完成
    EXCEPTION,       ///< 异常发生
    PROGRAM_EXIT     ///< 程序退出
};

/**
 * @brief 单步模式枚举
 */
enum class StepMode {
    NONE,   ///< 无单步模式
    INTO,   ///< 单步进入
    OVER,   ///< 单步跳过
    OUT     ///< 单步跳出
};

/**
 * @brief 调试信息结构体
 */
struct DebugInfo {
    std::unordered_map<size_t, size_t> line_to_address; ///< 行号到字节码地址的映射
    std::unordered_map<size_t, size_t> address_to_line; ///< 字节码地址到行号的映射
    std::unordered_map<std::string, size_t> function_addresses; ///< 函数名到地址的映射
    std::vector<std::string> source_lines; ///< 源代码行
};

/**
 * @brief 调试事件处理器接口
 */
class DebugEventHandler {
public:
    virtual ~DebugEventHandler() = default;
    virtual void on_event(DebugEvent event, size_t line, const std::string& message = "") = 0;
};

/**
 * @brief VimL虚拟机调试器
 */
class Debugger {
public:
    explicit Debugger(VM& vm);
    ~Debugger() = default;

    // 调试控制
    void start_debugging();
    void stop_debugging();

    // 断点管理
    void add_breakpoint(const std::string& filename, size_t line);
    void remove_breakpoint(const std::string& filename, size_t line);
    void clear_breakpoints();
    std::vector<std::pair<std::string, size_t>> list_breakpoints() const;

    // 执行控制
    void step_into();
    void step_over();
    void step_out();
    void continue_execution();

    // 变量检查
    Value get_variable(const std::string& name) const;
    std::unordered_map<std::string, Value> get_local_variables() const;
    std::unordered_map<std::string, Value> get_global_variables() const;

    // 调用栈检查
    std::vector<VM::StackFrame> get_call_stack() const;
    size_t get_current_line() const;
    std::string get_current_function() const;
    std::string get_current_file() const;

    // 事件处理
    void set_event_handler(std::unique_ptr<DebugEventHandler> handler);
    
    // 调试信息加载
    void load_debug_info(const std::string& filename, std::shared_ptr<DebugInfo> info);

    // 内部使用
    bool should_break_at(const std::string& filename, size_t line) const;
    void handle_breakpoint(const std::string& filename, size_t line);
    void notify_event(DebugEvent event, size_t line, const std::string& message = "");

private:
    VM& vm_;
    bool debugging_;
    StepMode step_mode_;
    size_t step_target_frame_;
    
    std::unordered_map<std::string, std::unordered_set<size_t>> breakpoints_;
    std::unordered_map<std::string, std::shared_ptr<DebugInfo>> debug_info_;
    std::unique_ptr<DebugEventHandler> handler_;
};

} // namespace viml